package control;

import static control.UITaskManagerBridge.OrderBy.CATEGORY;
import static control.UITaskManagerBridge.OrderBy.NAME;
import static control.UITaskManagerBridge.OrderBy.TIME_TO_SPEND;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.swing.JOptionPane;

import org.joda.time.LocalDate;

import ui.CreateEditTaskDialog.TaskData;
import entity.general.MinTime;
import entity.main.ObjectiveTaskManager;
import entity.main.Task;
import entity.main.Task.TaskType;

public class UITaskManagerBridge {

	private ObjectiveTaskManager taskManager;
	public static enum OrderBy {NAME, DEADLINE, TIME_TO_SPEND, CATEGORY};

	public UITaskManagerBridge(ObjectiveTaskManager otm)
	{
		taskManager = otm;
	}
	
	public UITaskManagerBridge() {
		taskManager = new ObjectiveTaskManager();
	}

	public void addTimeToTask(MinTime time, Task task)
	{
		task.addTimeSpent(time);
	}
	
	public void createTask(String name, TaskType type, String parentObjectiveName, LocalDate start, LocalDate deadline,
			String description, MinTime timeToSpend) {
		
		try
		{
			if(deadline != null)
			{
				if(parentObjectiveName != null)
				{
					taskManager.addTaskWithDeadline(name, type, parentObjectiveName, start, deadline, description, timeToSpend);
				}
				else
				{
					taskManager.addTaskWithDeadline(name, type,  start, deadline, description, timeToSpend);				
				}
			}
			else
			{
				if(parentObjectiveName != null)
				{
					taskManager.addTaskWithoutDeadline(name, type,  parentObjectiveName, start, description, timeToSpend);
				}
				else
				{
					taskManager.addTaskWithoutDeadline(name, type,  start, description, timeToSpend);				
				}			
			}
		}
		catch(Exception e)
		{
			JOptionPane.showMessageDialog(null,
				    e.getMessage(),
				    "Task Creation Error",
				    JOptionPane.ERROR_MESSAGE);		

		}
	}

	public void deleteTask(Task task)
	{
		taskManager.deleteTask(task);
	}

	public List<Task> filterTasksWithPin(OrderBy orderBy, String searchTerm, boolean showCompleted) {
		return filterTasks(orderBy, searchTerm, true, showCompleted);
	}

	public List <Task> filterTasks(OrderBy orderBy, String searchTerm, boolean showCompleted)
	{
		return filterTasks(orderBy, searchTerm, false, showCompleted);
	}
	
	public List <Task> filterTasks(OrderBy orderBy, String searchTerm, final boolean withPin, final boolean showCompleted)
	{
		if(withPin)
			System.out.println("With pin");
		else
			System.out.println("Without pin");			
		
		Set <Task> allTasks = taskManager.getTasks();
		Set <Task> filteredTasks = new HashSet <Task>();
		if(searchTerm != null)
		{
			for(Task t : allTasks)
			{
				if(!showCompleted && t.isCompleted())
					continue;
				
				if(withPin && t.isPinned())
				{
					filteredTasks.add(t);					
				}
				else if(t.getName().toLowerCase().contains(searchTerm.toLowerCase()))
//				if(t.getName().toLowerCase().startsWith(searchTerm.toLowerCase()))
				{
					filteredTasks.add(t);
				}
				else if(t.getParentObjective().getName().toLowerCase().contains(searchTerm.toLowerCase()))
//				else if(t.getParentObjective().getName().toLowerCase().startsWith(searchTerm.toLowerCase()))
				{
					filteredTasks.add(t);
				}
			}
		}
		else
		{
			for(Task t : allTasks)
			{
				if(!showCompleted && t.isCompleted())
					continue;
				filteredTasks.add(t);
			}
		}
		
		List <Task> tasksInOrder = new ArrayList <>(filteredTasks);

		Comparator <Task> comparator = null;
		
		if(orderBy == NAME)
		{
			comparator = new Comparator <Task> ()
				{
					@Override
					public int compare(Task arg0, Task arg1) {
						if(withPin)
						{
							if(arg0.isPinned() && !arg1.isPinned())
							{
								return -1;
							}
							else if(!arg0.isPinned() && arg1.isPinned())
							{
								return 1;
							}						
						}
						return arg0.getName().compareTo(arg1.getName());
					}
				};
		}
		else if(orderBy == TIME_TO_SPEND)
		{
			comparator = new Comparator <Task> ()
			{
				@Override
				public int compare(Task arg0, Task arg1) {
					if(withPin)
					{
						if(arg0.isPinned() && !arg1.isPinned())
						{
							return -1;
						}
						else if(!arg0.isPinned() && arg1.isPinned())
						{
							return 1;
						}						
					}
					
					Float t0 = arg0.getTimeSpentThisWeekPercentage();
					Float t1 = arg1.getTimeSpentThisWeekPercentage();
					MinTime timeToSpend0 = arg0.getTimePlanned();
					MinTime timeToSpend1 = arg1.getTimePlanned();
							
					if(t0.compareTo(t1) != 0)
					{
						return t0.compareTo(t1);
					}
					else if(timeToSpend1.compareTo(timeToSpend0) != 0)
					{
						return timeToSpend1.compareTo(timeToSpend0);
					}
					else					
						return arg0.getName().compareTo(arg1.getName());
				}
			};			
		}
		else if(orderBy == CATEGORY)
		{
			comparator = new Comparator <Task> ()
			{
				@Override
				public int compare(Task arg0, Task arg1) {
					if(withPin)
					{
						if(arg0.isPinned() && !arg1.isPinned())
						{
							return -1;
						}
						else if(!arg0.isPinned() && arg1.isPinned())
						{
							return 1;
						}						
					}

					String cName1 = arg0.getParentObjective().getName();
					String cName2 = arg1.getParentObjective().getName();
					
					if(cName1.compareTo(cName2) != 0)
					{
						return cName1.compareTo(cName2);
					}
					else					
						return arg0.getName().compareTo(arg1.getName());
				}
			};						
		}
		else
		{
			throw new UnsupportedOperationException("That order_by option is not supported yet");
		}
		Collections.sort(tasksInOrder, comparator);
		return tasksInOrder;
	}
	
	public void editTask(Task task, TaskData taskData)
	{
		taskManager.editTask(task, taskData);
	}

	public void toggleTaskCompleted(Task task) {
		taskManager.toggleTaskCompleted(task);
	}
		
	public void loadTaskData(File file) throws IOException, ClassNotFoundException
	{
		InputStream infile = new FileInputStream(file);
		InputStream buffer = new BufferedInputStream(infile);
		ObjectInput input = new ObjectInputStream(buffer);
		taskManager = (ObjectiveTaskManager)input.readObject();
	}

	public void saveTaskData(File file) throws IOException
	{
//		if(!file.exists())
		OutputStream outfile = new FileOutputStream(file);
		OutputStream outbuffer = new BufferedOutputStream(outfile);
		ObjectOutput output = new ObjectOutputStream(outbuffer);
		output.writeObject(taskManager);
		output.close();
	}

	public void setObjectiveTaskManager(
			ObjectiveTaskManager objectiveTaskManager) {
		taskManager = objectiveTaskManager;
	}


}
